﻿using System;
using System.Diagnostics.Contracts;
using System.IO;
//using Bamboo.Core;
//using Bamboo.Infrastructure.Repository.NHibernate;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Dialect;
using NHibernate.Tool.hbm2ddl;
using Bamboo.Core;
using Bamboo.Infrastructure.Repository.NHibernate;

namespace VietThinks.Mapping
{
    public abstract class RepositoryFactoryBuilderBase
    {
        protected Configuration configuration;
        protected Dialect dialect;

        /// <summary>
        /// Configures throw-away storage for automation testing
        /// </summary>
        /// <returns></returns>
        protected void Configure()
        {
            this.configuration = this.ConfigureCore();

            this.QuoteIdentifiers();
        }

        private void QuoteIdentifiers()
        {
            Contract.Assert(this.dialect != null);

            foreach (var mapping in this.configuration.ClassMappings)
            {
                if (!mapping.Table.IsQuoted)
                {
                    mapping.Table.Name = this.dialect.QuoteForTableName(mapping.Table.Name);
                }

                if (!mapping.Table.IsSchemaQuoted)
                {
                    mapping.Table.Schema = this.dialect.QuoteForSchemaName(mapping.Table.Schema);
                }

                foreach (var columnMapping in mapping.Table.ColumnIterator)
                {
                    if (!columnMapping.IsQuoted)
                    {
                        columnMapping.Name = this.dialect.QuoteForColumnName(columnMapping.Name);
                    }
                }
            }
        }

        protected abstract Configuration ConfigureCore();

        protected virtual void ExportSchemaCore(Action<string> processLog)
        {
            new SchemaExport(this.configuration).Execute(processLog ?? ((string s) => { }), true, false);
        }

        public void ExportSchema()
        {
            this.ExportSchemaCore(null);
        }

        public void ExportSchema(string logFileName)
        {
            Contract.Requires(configuration != null);

            using (var file = File.CreateText(logFileName))
            {
                this.ExportSchemaCore(file.WriteLine);
            }
        }

        protected virtual void UpdateSchemaCore(Action<string> processLog)
        {
            new SchemaUpdate(this.configuration).Execute(processLog ?? ((string s) => { }), true);
        }

        public void UpdateSchema()
        {
            this.UpdateSchemaCore(null);
        }

        public void UpdateSchema(string logFileName)
        {
            Contract.Requires(configuration != null);

            using (var file = File.CreateText(logFileName))
            {
                this.UpdateSchemaCore(file.WriteLine);
            }
        }

        public virtual IRepositoryFactory BuildRepositoryFactory()
        {
            if (this.configuration == null)
            {
                this.Configure();
            }

            return new RepositoryFactory(configuration.BuildSessionFactory());
        }
    }
}
